﻿#if UNITY_EDITOR
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using UnityEditor.Animations;
using VRC.SDK3.Avatars.ScriptableObjects;
using VRC.SDK3.Avatars.Components;
using static VRC.SDK3.Avatars.Components.VRCAvatarDescriptor;
using static UnityEditor.Experimental.GraphView.GraphView;

namespace AvatarLight {
    public class AvatarLightSetting : EditorWindow
    {
        private const string savePath = "Assets/AvatarLightForLilToon/GeneratedAnimation/";
        protected static GameObject root;
        protected static AnimatorController anc;
        protected List<GameObject> objs = new List<GameObject>();

        [MenuItem("工具/亮度动画生成")]
        public static void ShowWin()
        {
            GetWindow(typeof(AvatarLightSetting));
        }

        private void OnGUI()
        {
            using(var check = new EditorGUI.ChangeCheckScope())
            {
                root = EditorGUILayout.ObjectField("avatar", root, typeof(GameObject), true) as GameObject;
                if(check.changed)
                {
                    anc = GetVRCAvatarFXLayer(root);
                }
            }
            anc = EditorGUILayout.ObjectField("Fx", anc, typeof(AnimatorController), true) as AnimatorController;
            if(GUILayout.Button("确认生成")&&root!=null&&anc!=null)
            {
                if (EditorUtility.DisplayDialog("提示", "是否生成AvatarLight动画？这会直接修改你的AnimatorCOntroller" +
                    "，请确保当前选择的avatar是VRCSDK3 Avatar，且AnimatorController是VRCSDK3 Avatar的FX层", "确定", "取消"))
                {
                    if (SetAvatarLight())
                    {
                        EditorUtility.DisplayDialog("提示", "生成成功，请检查Avatar对应菜单和参数", "确定");
                    }
                    else
                    {
                        EditorUtility.DisplayDialog("提示", "生成失败", "确定");
                    }
                }
            }
            //EditorGUILayout.HelpBox("请先选择目标根对象", MessageType.Warning);
        }

        private AnimatorController GetVRCAvatarFXLayer(GameObject obj)
        {
            if (obj == null) return null;
            var descriptor = obj.GetComponent<VRCAvatarDescriptor>();
            foreach(var layer in descriptor.baseAnimationLayers)
            {
                if (layer.animatorController == null || layer.isDefault) continue;
                if (layer.type == VRCAvatarDescriptor.AnimLayerType.FX)
                    return layer.animatorController as AnimatorController;
            }
            return null;
        }

        private bool SetAvatarLight()
        {
            objs.Clear();
            FindAllmat(root.transform);
            if (objs.Count == 0)
            {
                Debug.LogWarning("没有找到liltoon材质的物体");
                return false;
            }
            /*
            foreach (var x in anc.animationClips)
            {
                var curves = AnimationUtility.GetAllCurves(x);
                Debug.Log(curves);
            }
            return;
            */

            //确保动画参数中存在AvatarLight
            bool isExist = false;
            foreach (var param in anc.parameters)
            {
                if (param.name.Equals("AvatarLight"))
                {
                    isExist = true;
                }
            }
            if (!isExist) anc.AddParameter("AvatarLight", AnimatorControllerParameterType.Float);



            //确保动画层中存在AvatarLight
            var layers = anc.layers;
            for (int i = layers.Length - 1; i >= 0; i--)
            {
                if (layers[i].name.Equals("AvatarLight"))
                {
                    anc.RemoveLayer(i);
                    break;
                };
            }
            //anc.AddLayer("AvatarLight");


            //创建动画
            AnimationCurve animationCurve = new();
            animationCurve.AddKey(0, 0);
            animationCurve.AddKey(1, 1);
            AnimationClip ac = new();
            foreach (var x in objs)
            {
                ac.SetCurve(
                    AnimationUtility.CalculateTransformPath(x.transform, root.transform),
                    typeof(SkinnedMeshRenderer),
                    "material._LightMinLimit",
                    animationCurve);
            }
            
            //保存动画
            if (!System.IO.Directory.Exists(savePath))
                System.IO.Directory.CreateDirectory(savePath);
            ac.name = root.name + "_AvatarLightClip";
            AssetDatabase.CreateAsset(ac, savePath + ac.name + ".anim");


            AnimatorControllerLayer newlayer = new()
            {
                defaultWeight = 1.0f,
                name = "AvatarLight",
                stateMachine = new AnimatorStateMachine()
                {
                    name = "AvatarLight",
                    hideFlags = HideFlags.HideInHierarchy,
                },
            };

            newlayer.stateMachine.AddState(new AnimatorState()
            {
                motion = ac,
                name = "AvatarLight",
                timeParameter = "AvatarLight",
                timeParameterActive = true,
                writeDefaultValues = true,
                speedParameterActive = false,
            }, 
            new Vector3(0,0,0));
            
            anc.AddLayer(newlayer);

            //参考https://discussions.unity.com/t/animator-controller-layer-and-default-weight/698547/2
            AssetDatabase.AddObjectToAsset(newlayer.stateMachine, AssetDatabase.GetAssetPath(anc));
            //参考https://discussions.unity.com/t/modify-animatorcontroller-through-script-and-save-it/728542/9
            foreach (var childState in newlayer.stateMachine.states)
            {
                if (AssetDatabase.GetAssetPath(childState.state).Length == 0)
                {
                    childState.state.hideFlags = HideFlags.HideInHierarchy;
                    AssetDatabase.AddObjectToAsset(childState.state, AssetDatabase.GetAssetPath(anc));
                }
            }
            //EditorUtility.SetDirty(anc);
            //AssetDatabase.SaveAssets();
            //AssetDatabase.Refresh();
            return true;
        }

        /// <summary>
        /// 递归查找所有带有liltoon材质的GameObject并存入objs
        /// </summary>
        /// <param name="obj"></param>
        private void FindAllmat(Transform obj)
        {
            var t = obj.GetComponent<SkinnedMeshRenderer>();
            List<Material> materials = new List<Material>();
            
            if(t!=null)
            {
                t.GetSharedMaterials(materials);
                //t.GetMaterials(materials);
                bool b = false;
                foreach(var m in materials)
                {
                    string name = m.shader.name.ToLower();
                    if (name.Contains("liltoon"))
                    { b = true; break; }
                }
                
                if(b)objs.Add(obj.gameObject);
            }

            for(int i=obj.childCount-1;i>=0;i--)
            {
                var child = obj.GetChild(i);
                if(child!=null)
                    FindAllmat(child);
            }
        }


    }
}
#endif